package com.xuelang.pipeline.artifact.app.resource.impl;

import com.alibaba.fastjson2.JSON;
import com.xuelang.jadp.client.sys.dto.UserInfoDTO;
import com.xuelang.pipeline.artifact.app.harborv2.ArtifactService;
import com.xuelang.pipeline.artifact.app.harborv2.enums.ArtifactReferenceAdditionEnum;
import com.xuelang.pipeline.artifact.app.nexus3v1.SearchAssetService;
import com.xuelang.pipeline.artifact.app.nexus3v1.request.SearchAssetQuery;
import com.xuelang.pipeline.artifact.app.nexus3v1.response.SearchAssetResponse;
import com.xuelang.pipeline.artifact.app.nexus3v1.xo.ApiResponseXO;
import com.xuelang.pipeline.artifact.app.resource.RepositoryComponentService;
import com.xuelang.pipeline.artifact.app.resource.converter.RepositoryComponentDTOToRepositoryComponentConverter;
import com.xuelang.pipeline.artifact.client.common.constant.Constant;
import com.xuelang.pipeline.artifact.client.common.request.PageParam;
import com.xuelang.pipeline.artifact.client.common.result.PageRecord;
import com.xuelang.pipeline.artifact.client.common.util.BizAssert;
import com.xuelang.pipeline.artifact.client.resource.dto.RepositoryAssetBuildHistoryDTO;
import com.xuelang.pipeline.artifact.client.resource.dto.RepositoryAssetDTO;
import com.xuelang.pipeline.artifact.client.resource.dto.RepositoryComponentDTO;
import com.xuelang.pipeline.artifact.client.resource.dto.RepositoryComponentQuery;
import com.xuelang.pipeline.artifact.domain.resource.ArtifactUser;
import com.xuelang.pipeline.artifact.domain.resource.RepositoryComponent;
import com.xuelang.pipeline.artifact.domain.resource.service.ArtifactUserDomainService;
import com.xuelang.pipeline.artifact.domain.resource.service.RepositoryComponentDomainService;
import com.xuelang.sys.app.sys.UserManagerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 制品组件服务实现类
 *
 * @author xiwen.zxg
 * @since 2024/5/15
 */
@Service
public class RepositoryComponentServiceImpl implements RepositoryComponentService {

    @Autowired
    RepositoryComponentDomainService repositoryComponentDomainService;
    @Autowired
    SearchAssetService searchAssetService;
    @Autowired
    ArtifactService artifactService;
    @Autowired
    UserManagerService userManagerService;
    @Autowired
    ArtifactUserDomainService artifactUserDomainService;

    private RepositoryComponentDTO fullfillCreator(RepositoryComponentDTO repositoryComponentDTO){
        String creatorId = repositoryComponentDTO.getCreatorId();
        UserInfoDTO user = userManagerService.getUserById(creatorId);
        if (Objects.nonNull(user)) {
            repositoryComponentDTO.setCreator(user.getRealName());
        }else{
            repositoryComponentDTO.setCreator("[未知用户]");
        }
        return repositoryComponentDTO;
    }

    private RepositoryComponentDTO fullfillPusherName(RepositoryComponentDTO repositoryComponentDTO) {
        ArtifactUser user = artifactUserDomainService.queryArtifactUserByArtifactUserIdAndToolUuid(
                repositoryComponentDTO.getPushUser(),
                repositoryComponentDTO.getArtifactUuid()
        );
        if (Objects.nonNull(user)) {
            repositoryComponentDTO.setPushUserName(user.getUserName());
        }else{
            repositoryComponentDTO.setPushUserName("[未知用户]");
        }
        return repositoryComponentDTO;
    }

    @Override
    public PageRecord<RepositoryComponentDTO> pageList(PageParam<RepositoryComponentQuery> dtoPageParam) {
        RepositoryComponentQuery condition = dtoPageParam.getCondition();
        condition = condition == null ? new RepositoryComponentQuery() : condition;
        PageRecord<RepositoryComponent> pageRecord = repositoryComponentDomainService.pageList(
                dtoPageParam.getCurrentPage(),
                dtoPageParam.getPageSize(),
                condition);
        return new PageRecord<>(
                pageRecord.getCurrentPage(),
                pageRecord.getPageSize(),
                pageRecord.getTotalCount(),
                pageRecord.getTotalPages(),
                pageRecord.getRecords().stream()
                        .map(RepositoryComponentDTOToRepositoryComponentConverter.INSTANCE::repositoryComponentToRepositoryComponentDTO)
                        .map(this::fullfillCreator)
                        .map(this::fullfillPusherName)
                        .collect(Collectors.toList()));
    }

    @Override
    public List<RepositoryComponentDTO> list(RepositoryComponentQuery repositoryComponentQuery) {
        return repositoryComponentDomainService.list(repositoryComponentQuery).stream()
                .map(RepositoryComponentDTOToRepositoryComponentConverter.INSTANCE::repositoryComponentToRepositoryComponentDTO)
                .map(this::fullfillCreator)
                .map(this::fullfillPusherName)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(String restId) {
        BizAssert.notNull(restId, "id不能为空");
        return repositoryComponentDomainService.delete(restId);
    }


    @Override
    public RepositoryComponentDTO query(String restId) {
        BizAssert.notNull(restId, "id不能为空");
        RepositoryComponent repositoryComponent = repositoryComponentDomainService.query(restId);
        return RepositoryComponentDTOToRepositoryComponentConverter.INSTANCE.repositoryComponentToRepositoryComponentDTO(repositoryComponent);
    }

    @Override
    public List<RepositoryAssetDTO> listAssetsBytRestId(String restId) {
        List<RepositoryAssetDTO> list = new ArrayList<>();
        RepositoryComponent repositoryComponent = repositoryComponentDomainService.query(restId);
        if (null != repositoryComponent) {
            String hosteInstanceRepositoryName = getHostedInstanceRepositoryName(repositoryComponent.getInstanceRepositoryName());
            SearchAssetQuery searchAssetQuery = new SearchAssetQuery();
            searchAssetQuery.setRepository(hosteInstanceRepositoryName);
            searchAssetQuery.setFormat(repositoryComponent.getFormat());
            searchAssetQuery.setGroup(Optional.ofNullable(repositoryComponent.getGroupId()).orElse(""));
            searchAssetQuery.setName(Optional.ofNullable(repositoryComponent.getNameId()).orElse(""));
            searchAssetQuery.setVersion(Optional.ofNullable(repositoryComponent.getVersion()).orElse(""));
            ApiResponseXO<SearchAssetResponse> apiResponseXO =  searchAssetService.searchAsset(searchAssetQuery);
            if (apiResponseXO.isSuccess() && apiResponseXO.getData() != null && apiResponseXO.getData().getItems() != null) {
                apiResponseXO.getData().getItems().forEach(asset ->
                        list.add(
                                RepositoryAssetDTO.builder()
                                        .assetId(asset.getId())
                                        .assetName(Optional.ofNullable(asset.getPath()).map(path -> path.substring(path.lastIndexOf(Constant.DEFAULT_URL_PATH_SEPARATOR) + 1)).orElse(""))
                                        .assetPath(asset.getPath())
                                        .downLoadUrl(asset.getDownloadUrl())
                                        .format(asset.getFormat())
                                        .fileSize(asset.getFileSize())
                                        .lastModified(asset.getLastModified())
                                        .repository(asset.getRepository())
                                        .build()
                        )
                );
            }
        }

        return list;
    }

    @Override
    public List<RepositoryAssetBuildHistoryDTO> dockerArtifactBuildHistory(String restId) {
        RepositoryComponent repositoryComponent = repositoryComponentDomainService.query(restId);
        if (null != repositoryComponent) {
            // restId拼接规则
            // String restId = mainDigest + Constant.DEFAULT_MIDDLE_SEPARATOR + packageName + Constant.DEFAULT_MIDDLE_SEPARATOR + currentPushVersion;
            String packageNameAndPushVersionOfRestId = Constant.DEFAULT_MIDDLE_SEPARATOR + repositoryComponent.getPackageName()
                    + Constant.DEFAULT_MIDDLE_SEPARATOR + repositoryComponent.getVersion();
            String harborRestId = restId.replace(packageNameAndPushVersionOfRestId, "");
            ApiResponseXO<String> stringApiResponseXO = artifactService.artifactAdditionInfo(
                    repositoryComponent.getInstanceRepositoryName(),
                    repositoryComponent.getPackageName(),
                    harborRestId,
                    ArtifactReferenceAdditionEnum.BUILD_HISTORY.getId()

            );
            if (stringApiResponseXO.isSuccess()) {
                List<RepositoryAssetBuildHistoryDTO> repositoryAssetBuildHistoryDTOS = JSON.parseArray(stringApiResponseXO.getData(), RepositoryAssetBuildHistoryDTO.class);
                Optional.ofNullable(repositoryAssetBuildHistoryDTOS).ifPresent(list -> list.forEach(RepositoryComponentServiceImpl::formatCreated));
                return repositoryAssetBuildHistoryDTOS;
            }
        }
        return Collections.emptyList();
    }

    private static final DateTimeFormatter FORMAT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static void formatCreated(RepositoryAssetBuildHistoryDTO data) {
        try {
            data.setCreated(ZonedDateTime.parse(data.getCreated(), DateTimeFormatter.ISO_OFFSET_DATE_TIME).format(FORMAT_DATE_TIME_FORMATTER));
        } catch (Exception e) {
            data.setCreated(data.getCreated());
        }
    }

    private String getInstanceRepositoryName(String repositoryName) {
        if (null == repositoryName) {
            return repositoryName;
        }
        if (!repositoryName.startsWith("hosted-")) {
            return repositoryName;
        }
        return repositoryName.replaceFirst("hosted-", "");
    }
    private String getHostedInstanceRepositoryName(String repositoryName) {
        if (null == repositoryName) {
            return repositoryName;
        }
        if (repositoryName.startsWith("hosted-")) {
            return repositoryName;
        }
        return "hosted-" + repositoryName;
    }

}
